package com.github.filter;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.util.AESEncrypt;
import com.github.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@Component
public class DecryptFilter extends OncePerRequestFilter {
    // 在控制器或服务中添加测试
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private static final List<String> FILTER_URI = new ArrayList<>();

    static {
        FILTER_URI.add("/api/server_login");
        FILTER_URI.add("/api/server_logout");
        FILTER_URI.add("/api/get_setting");
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        String requestURI = request.getRequestURI();
        return !requestURI.startsWith("/api/");
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//        logger.info("DecryptFilter-->response-->" + response);
//        logger.info("DecryptFilter-->request-->" + request);
        logger.info("DecryptFilter-->getClientIp-->" + Utils.getClientIp(request));
        String path = request.getRequestURI();
//        logger.info("DecryptFilter-->path-->" + path);
        if (!FILTER_URI.contains(path)) {
            filterChain.doFilter(request, response);
            return;
        }

        // 读取请求体
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = request.getReader();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }

        // 解析JSON字符串
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode rootNode = objectMapper.readTree(sb.toString());

        // 获取并解密payload字段
        String encryptedPayload = rootNode.path("payload").asText();
        String decryptedPayload = AESEncrypt.decrypt(encryptedPayload);
        logger.info("DecryptFilter-->decryptedPayload-->" + decryptedPayload);

        // 创建一个新的HttpServletRequestWrapper来替换原始请求
        HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) {
            @Override
            public BufferedReader getReader() throws IOException {
                return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(decryptedPayload.getBytes(StandardCharsets.UTF_8))));
            }

            @Override
            public ServletInputStream getInputStream() throws IOException {
                return new ServletInputStream() {
                    private final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decryptedPayload.getBytes(StandardCharsets.UTF_8));

                    @Override
                    public boolean isFinished() {
                        return byteArrayInputStream.available() == 0;
                    }

                    @Override
                    public boolean isReady() {
                        return true;
                    }

                    @Override
                    public void setReadListener(ReadListener readListener) {
                        throw new UnsupportedOperationException("Not supported");
                    }

                    @Override
                    public int read() throws IOException {
                        return byteArrayInputStream.read();
                    }
                };
            }
        };
        filterChain.doFilter(requestWrapper, response);
    }
}
